home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 051-075 / scopedisk75 / ispell / src / ispell.c < prev    next >
C/C++ Source or Header  |  1995-03-19  |  12KB  |  695 lines

  1. /* -*- Mode:Text -*- */
  2. /*
  3.  * ispell.c - An interactive spelling corrector.
  4.  *
  5.  * Copyright (c), 1983, by Pace Willisson
  6.  * Permission for non-profit use is hereby granted.
  7.  * All other rights reserved.
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <ctype.h>
  12. #include "ispell.h"
  13.  
  14. #define NOPARITY 0x7f 
  15.  
  16. FILE *infile;
  17. FILE *outfile;
  18.  
  19. givehelp ()
  20. {
  21.     erase ();
  22.     printf ("Whenever a word is found that is not in the dictionary,\r\n");
  23.     printf ("it is printed on the first line of the screen.  If the dictionary\r\n");
  24.     printf ("contains any similar words, they are listed with a single digit\r\n");
  25.     printf ("next to each one.  You have the option of replacing the word\r\n");
  26.     printf ("completely, or choosing one of the suggested words.\r\n");
  27.     printf ("\r\n");
  28.     printf ("Commands are:\r\n\r\n");
  29.     printf ("R       Replace the misspelled word completely.\r\n");
  30.     printf ("Space   Accept the word this time only\r\n");
  31.     printf ("A       Accept the word for the rest of this file.\r\n");
  32.     printf ("I       Accept the word, and put it in your private dictionary.\r\n");
  33.     printf ("0-9     Replace with one of the suggested words.\r\n");
  34.     printf ("Q       Write the rest of this file, ignoring misspellings, ");
  35.     printf (         "and start next file.\r\n");
  36.     printf ("X       Exit immediately.  Asks for conformation.  ");
  37.     printf (         "Leaves file unchanged.\r\n");
  38.     printf ("!       Shell escape.\r\n");
  39.     printf ("^L      Redraw screen.\r\n");
  40.     printf ("\r\n\r\n");
  41.     printf ("-- Type space to continue --");
  42.     fflush (stdout);
  43.     getchar ();
  44. }
  45.  
  46.  
  47. char *getline();
  48.  
  49. int lflag = 0;
  50. int aflag = 0;
  51. int fflag = 0;
  52. int sflag = 0;
  53.  
  54. char *askfilename;
  55.  
  56. usage ()
  57. {
  58.     fprintf (stderr, "Usage: spell [ file ... | -a | -l | -f file | -s ]\n");
  59.     exit (1);
  60. }
  61.  
  62. main (argc, argv)
  63. char **argv;
  64. {
  65.     argv++;
  66.     argc--;
  67.     while (argc && **argv == '-') {
  68.         switch ((*argv)[1]) {
  69.         case 'a':
  70.             aflag++;
  71.             break;
  72.         case 'f':
  73.             fflag++;
  74.             argv++; argc--;
  75.             if (argc == 0)
  76.                 usage ();
  77.             askfilename = *argv;
  78.             break;
  79.         case 'l':
  80.             lflag++;
  81.             break;
  82.         case 's':
  83.             sflag++;
  84.             break;
  85.         }
  86.         argv++; argc--;
  87.     }
  88.  
  89.     if (!argc && !lflag && !aflag)
  90.         usage ();
  91.  
  92.     if (linit () < 0)
  93.         exit (0);
  94.  
  95.     treeinit ();
  96.  
  97.     if (aflag) {
  98.         askmode ();
  99.         exit (0);
  100.     }
  101.  
  102.     if (lflag) {
  103.         infile = stdin;
  104.         checkfile ();
  105.         exit (0);
  106.     }
  107.  
  108.     terminit ();
  109.  
  110.     while (argc--)
  111.         dofile (*argv++);
  112.  
  113.     done ();
  114. }
  115.  
  116. char firstbuf[BUFSIZ], secondbuf[BUFSIZ];
  117. char *currentchar;
  118. char token[BUFSIZ];
  119.  
  120. int quit;
  121.  
  122. char *currentfile = NULL;
  123.  
  124. dofile (filename)
  125. char *filename;
  126. {
  127.     int c;
  128.     char    bakfile[256];
  129.  
  130.     currentfile = filename;
  131.  
  132.     if ((infile = fopen (filename, "r")) == NULL) {
  133.         fprintf (stderr, "Can't open %s\r\n", filename);
  134.         sleep (2);
  135.         return;
  136.     }
  137.  
  138.     if (access (filename, 2) < 0) {
  139.         fprintf (stderr, "Can't write to %s\r\n", filename);
  140.         sleep (2);
  141.         return;
  142.     }
  143.  
  144. #ifndef AMIGA
  145.     strcpy (tempfile, "/usr/tmp/spellXXXXXX");
  146. #else
  147.         strcpy(tempfile, TMPDIR);
  148.  
  149. #if USEDEVICES
  150.     strcat(tempfile, "ispellXXXXXX");
  151. #else
  152.     strcat(tempfile, "/ispellXXXXXX");
  153. #endif
  154.  
  155. #endif
  156.     mktemp (tempfile);
  157.     if ((outfile = fopen (tempfile, "w")) == NULL) {
  158.         fprintf (stderr, "Can't create %s\r\n", tempfile);
  159.         sleep (2);
  160.         return;
  161.     }
  162.  
  163.     quit = 0;
  164.  
  165.     checkfile ();
  166.  
  167.     fclose (infile);
  168.     fclose (outfile);
  169.  
  170.     treeoutput ();
  171.  
  172.     if ((infile = fopen (tempfile, "r")) == NULL) {
  173.         fprintf (stderr, "tempoary file disappeared (%s)\r\n", tempfile);    
  174.         sleep (2);
  175.         return;
  176.     }
  177.  
  178.     sprintf(bakfile, "%s.bak", filename);
  179.     if(link(filename, bakfile) == 0)
  180.         unlink(filename);
  181.  
  182.     if ((outfile = fopen (filename, "w")) == NULL) {
  183.         fprintf (stderr, "can't create %s\r\n", filename);
  184.         sleep (2);
  185.         return;
  186.     }
  187.  
  188.     while ((c = getc (infile)) != EOF)
  189.         putc (c, outfile);
  190.  
  191.     fclose (infile);
  192.     fclose (outfile);
  193.  
  194.     unlink (tempfile);
  195. }
  196.  
  197. checkfile ()
  198. {
  199.     int c;
  200.     char *p;
  201.     int len;
  202.  
  203.     secondbuf[0] = 0;
  204.     currentchar = secondbuf;
  205.  
  206.     while (1) {
  207.         strcpy (firstbuf, secondbuf);
  208.         if (quit) {    /* quit can't be set in l mode */
  209.             while (fgets (secondbuf, sizeof secondbuf, infile) != NULL)
  210.                 fputs (secondbuf, outfile);
  211.             break;
  212.         }
  213.  
  214.         if (fgets (secondbuf, sizeof secondbuf, infile) == NULL)
  215.             break;
  216.         currentchar = secondbuf;
  217.         
  218.         len = strlen (secondbuf) - 1;
  219.         if (secondbuf [ len ] == '\n')
  220.             secondbuf [ len ] = 0;
  221.  
  222.         /* if this is a formatter command, skip over it */
  223.         if (*currentchar == '.') {
  224.             while (*currentchar && !isspace (*currentchar)) {
  225.                 if (!lflag)
  226.                     putc (*currentchar, outfile);
  227.                 currentchar++;
  228.             }
  229.             if (*currentchar == 0) {
  230.                 putc ('\n', outfile);
  231.                 continue;
  232.             }
  233.         }
  234.  
  235.         while (1) {
  236.             while (*currentchar && !isalpha (*currentchar)) {
  237.                 /* formatting escape sequences */
  238.                 if (*currentchar == '\\') {
  239.                     if(currentchar[1] == 'f') {
  240.                     /* font change: \fX */
  241.                     copyout(¤tchar, 3);
  242.                     continue;
  243.                     }
  244.                     else if(currentchar[1] == 's') {
  245.                     /* size change */
  246.                     if(currentchar[2] < 6 &&
  247.                        currentchar[2] != 0)
  248.                         /* two digit size */
  249.                         copyout(¤tchar, 4);
  250.                     else
  251.                         /* one digit size */
  252.                         copyout(¤tchar, 3);
  253.                     continue;
  254.                     }
  255.                     else if(currentchar[1] == '(') {
  256.                     /* extended char set escape: \(XX */
  257.                     copyout(¤tchar, 4);
  258.                     continue;
  259.                     }
  260.                 }
  261.  
  262.                 if (!lflag)
  263.                     putc (*currentchar, outfile);
  264.                 currentchar++;
  265.             }
  266.  
  267.             if (*currentchar == 0)
  268.                 break;
  269.  
  270.             p = token;
  271.             while (isalpha (*currentchar))
  272.                 *p++ = *currentchar++;
  273.             *p = 0;
  274.             if (lflag) {
  275.                 if (!good (token))
  276.                     printf ("%s\r\n", token);
  277.             } else {
  278.                 if (!quit)
  279.                 correct (token, ¤tchar);
  280.             }
  281.             if (!lflag)
  282.                 fprintf (outfile, "%s", token);
  283.         }
  284.         putc ('\n', outfile);
  285.     }
  286. }
  287.  
  288. char possibilities[10][BUFSIZ];
  289. int pcount;
  290.  
  291. correct (token, currentchar)
  292. char *token;
  293. char **currentchar;
  294. {
  295.     int c;
  296.     int i;
  297.     char *p;
  298.     int len;
  299.     char *begintoken;
  300.  
  301.     len = strlen (token);
  302.     begintoken = *currentchar - len;
  303.  
  304. checkagain:
  305.     if (good (token))
  306.         return;
  307.  
  308.     erase ();
  309.     printf ("    %s", token);
  310.     if (currentfile)
  311.         printf ("              File: %s", currentfile);
  312.     printf ("\r\n\r\n");
  313.  
  314.     makepossibilities (token);
  315.  
  316.     for (i = 0; i < 10; i++) {
  317.         if (possibilities[i][0] == 0)
  318.             break;
  319.         printf ("%d: %s\r\n", i, possibilities[i]);
  320.     }
  321.  
  322.     move (15, 0);
  323.     printf ("%s\r\n", firstbuf);
  324.  
  325.     for (p = secondbuf; p != begintoken; p++)
  326.         putchar (*p);
  327.     inverse ();
  328.     for (i = strlen (token); i > 0; i--)
  329.         putchar (*p++);
  330.     normal ();
  331.     while (*p)
  332.         putchar (*p++);
  333.     printf ("\r\n");
  334.  
  335.     while (1) {
  336.         switch (c = (getchar () & NOPARITY)) {
  337.         case 'Z' & 037:
  338.             stop ();
  339.             erase ();
  340.             goto checkagain;
  341.         case ' ':
  342.             erase ();
  343.             return;
  344.         case 'x': case 'X':
  345.             printf ("Are you sure you want to throw away your changes? ");
  346.             c = (getchar () & NOPARITY);
  347.             if (c == 'y' || c == 'Y') {
  348.                 erase ();
  349.                 done ();
  350.             }
  351.             putchar (7);
  352.             goto checkagain;
  353.         case 'i': case 'I':
  354.             treeinsert (token, 1);
  355.             erase ();
  356.             return;
  357.         case 'a': case 'A':
  358.             treeinsert (token, 0);
  359.             erase ();
  360.             return;
  361.         case 'L' & 037:
  362.             goto checkagain;
  363.         case '?':
  364.             givehelp ();
  365.             goto checkagain;
  366.         case '!':
  367.             {
  368.                 char buf[200];
  369.                 move (18, 0);
  370.                 putchar ('!');
  371.                 if (getline (buf) == NULL) {
  372.                     putchar (7);
  373.                     erase ();
  374.                     goto checkagain;
  375.                 }
  376.                 printf ("\r\n");
  377.                 shellescape (buf);
  378.                 erase ();
  379.                 goto checkagain;
  380.             }
  381.         case 'r': case 'R':
  382.             move (18, 0);
  383.             printf ("Replace with: ");
  384.             if (getline (token) == NULL) {
  385.                 putchar (7);
  386.                 erase ();
  387.                 goto checkagain;
  388.             }
  389.             inserttoken (secondbuf, begintoken, token, currentchar);
  390.             erase ();
  391.             goto checkagain;
  392.         case '0': case '1': case '2': case '3': case '4':
  393.         case '5': case '6': case '7': case '8': case '9':
  394.             if (possibilities[c - '0'][0] != 0) {
  395.                 strcpy (token, possibilities[c - '0']);
  396.                 inserttoken (secondbuf, begintoken, token, currentchar);                erase ();
  397.                 return;
  398.             }
  399.             putchar (7);
  400.             break;
  401.         case 'q': case 'Q':
  402.             quit = 1;
  403.             erase ();
  404.             return;
  405.         default:
  406.             putchar (7);
  407.             break;
  408.         }
  409.     }
  410. }
  411.  
  412. inserttoken (buf, start, token, currentchar)
  413. char *buf, *start, *token;
  414. char **currentchar;
  415. {
  416.     char copy[BUFSIZ];
  417.     char *p, *q;
  418.  
  419.     strcpy (copy, buf);
  420.  
  421.     for (p = buf, q = copy; p != start; p++, q++)
  422.         *p = *q;
  423.     while (*token)
  424.         *p++ = *token++;
  425.     q += *currentchar - start;
  426.     *currentchar = p;
  427.     while (*p++ = *q++)
  428.         ;
  429. }
  430.  
  431.  
  432. makepossibilities (word)
  433. char word[];
  434. {
  435.     int i;
  436.  
  437.     for (i = 0; i < 10; i++)
  438.         possibilities[i][0] = 0;
  439.     pcount = 0;
  440.  
  441.     if (pcount < 10) wrongletter (word);
  442.     if (pcount < 10) extraletter (word);
  443.     if (pcount < 10) missingletter (word);
  444.     if (pcount < 10) transposedletter (word);
  445.  
  446. }
  447.  
  448. char *cap();
  449.  
  450. insert (word)
  451. char *word;
  452. {
  453.     int i;
  454.  
  455.     for (i = 0; i < pcount; i++)
  456.         if (strcmp (possibilities[i], word) == 0)
  457.             return (0);
  458.  
  459.     strcpy (possibilities[pcount++], word);
  460.     if (pcount >= 10)
  461.         return (-1);
  462.     else
  463.         return (0);
  464. }
  465.  
  466. wrongletter (word)
  467. char word[];
  468. {
  469.     int i, c, n;
  470.     char newword[BUFSIZ];
  471.  
  472.     n = strlen (word);
  473.     strcpy (newword, word);
  474.  
  475.     for (i = 0; i < n; i++) {
  476.         for (newword[i] = 'A'; newword[i] <= 'Z'; newword[i]++) {
  477.             if (good (newword)) {
  478.                 if (insert (cap (newword, word)) < 0)
  479.                     return;
  480.             }
  481.         }
  482.         newword[i] = word[i];
  483.     }
  484. }
  485.  
  486. extraletter (word)
  487. char word[];
  488. {
  489.     char newword[BUFSIZ], *p, *s, *t;
  490.  
  491.     if (strlen (word) < 3)
  492.         return;
  493.  
  494.     for (p = word; *p; p++) {
  495.         for (s = word, t = newword; *s; s++)
  496.             if (s != p)
  497.                 *t++ = *s;
  498.         *t = 0;
  499.         if (good (newword)) {
  500.             if (insert (cap (newword, word)) < 0)
  501.                 return;
  502.         }
  503.     }
  504. }
  505.  
  506. missingletter (word)
  507. char word[];
  508. {
  509.     char newword[BUFSIZ], *p, *r, *s, *t;
  510.  
  511.     for (p = word; p == word || p[-1]; p++) {
  512.         for (s = newword, t = word; t != p; s++, t++)
  513.             *s = *t;
  514.         r = s++;
  515.         while (*t)
  516.             *s++ = *t++;
  517.         *s = 0;
  518.         for (*r = 'A'; *r <= 'Z'; (*r)++) {
  519.             if (good (newword)) {
  520.                 if (insert (cap (newword, word)) < 0)
  521.                     return;
  522.             }
  523.         }
  524.     }
  525. }
  526.  
  527. transposedletter (word)
  528. char word[];
  529. {
  530.     char newword[BUFSIZ];
  531.     int t;
  532.     char *p;
  533.  
  534.     strcpy (newword, word);
  535.     for (p = newword; p[1]; p++) {
  536.         t = p[0];
  537.         p[0] = p[1];
  538.         p[1] = t;
  539.         if (good (newword)) {
  540.             if (insert (cap (newword, word)) < 0)
  541.                 return;
  542.         }
  543.         t = p[0];
  544.         p[0] = p[1];
  545.         p[1] = t;
  546.     }
  547. }
  548.  
  549. char *
  550. cap (word, pattern)
  551. char word[], pattern[];
  552. {
  553.     static char newword[BUFSIZ];
  554.     char *p, *q;
  555.  
  556.     if (*word == 0)
  557.         return;
  558.  
  559.     if (isupper (pattern[0])) {
  560.         if (isupper (pattern[1])) {
  561.             for (p = word, q = newword; *p; p++, q++) {
  562.                 if (islower (*p))
  563.                     *q = toupper (*p);
  564.                 else
  565.                     *q = *p;
  566.             }
  567.             *q = 0;
  568.         } else {
  569.             if (islower (word [0]))
  570.                 newword[0] = toupper (word[0]);
  571.             else
  572.                 newword[0] = word[0];
  573.  
  574.             for (p = word + 1, q = newword + 1; *p; p++, q++)
  575.                 if (isupper (*p))
  576.                     *q = tolower (*p);
  577.                 else
  578.                     *q = *p;
  579.  
  580.             *q = 0;
  581.         }
  582.     } else {
  583.         for (p = word, q = newword; *p; p++, q++)
  584.             if (isupper (*p))
  585.                 *q = tolower (*p);
  586.             else
  587.                 *q = *p;
  588.         *q = 0;
  589.     }
  590.     return (newword);
  591. }
  592.  
  593. char *
  594. getline (s)
  595. char *s;
  596. {
  597.     char *p;
  598.     int c;
  599.  
  600.     p = s;
  601.  
  602.     while (1) {
  603.         c = (getchar () & NOPARITY);
  604.         if (c == '\\') {
  605.             putchar ('\\');
  606.             c = (getchar () & NOPARITY);
  607.             backup ();
  608.             putchar (c);
  609.             *p++ = c;
  610.         } else if (c == ('G' & 037)) {
  611.             return (NULL);
  612.         } else if (c == '\n' || c == '\r') {
  613.             *p = 0;
  614.             return (s);
  615.         } else if (c == erasechar) {
  616.             if (p != s) {
  617.                 p--;
  618.                 backup ();
  619.                 putchar (' ');
  620.                 backup ();
  621.             }
  622.         } else if (c == killchar) {
  623.             while (p != s) {
  624.                 p--;
  625.                 backup ();
  626.                 putchar (' ');
  627.                 backup ();
  628.             }
  629.         } else {
  630.             *p++ = c;
  631.             putchar (c);
  632.         }
  633.     }
  634. }
  635.  
  636. askmode ()
  637. {
  638.     char buf[BUFSIZ];
  639.     int i;
  640.  
  641.     if (fflag) {
  642.         if (freopen (askfilename, "w", stdout) == NULL) {
  643.             fprintf (stderr, "Can't create %s\n", askfilename);
  644.             exit (1);
  645.         }
  646.     }
  647.  
  648.     setbuf (stdin, NULL);
  649.     setbuf (stdout, NULL);
  650.  
  651.     while (gets (buf) != NULL) {
  652.         if (good (buf)) {
  653.             if (rootword[0] == 0) {
  654.                 printf ("*\n");    /* perfect match */
  655.             } else {
  656.                 printf ("+ %s\n", rootword);
  657.             }
  658.         } else {
  659.             makepossibilities (buf);
  660.             if (possibilities[0][0]) {
  661.                 printf ("& ");
  662.                 for (i = 0; i < 10; i++) {
  663.                     if (possibilities[i][0] == 0)
  664.                         break;
  665.                     printf ("%s ", possibilities[i]);
  666.                 }
  667.                 printf ("\n");
  668.             } else {
  669.                 printf ("#\n");
  670.             }
  671.         }
  672.         if (sflag) {
  673.             stop ();
  674.             if (fflag) {
  675.                 rewind (stdout);
  676.                 creat (askfilename, 0666);
  677.             }
  678.         }
  679.     }
  680. }
  681.  
  682.  
  683. copyout(cc, cnt)
  684. char    **cc;
  685. {
  686.     while (--cnt >= 0) {
  687.         if (*(*cc) == 0)
  688.             break;
  689.         if (!lflag)
  690.             putc (*(*cc), outfile);
  691.         (*cc)++;
  692.     }
  693.  
  694. }
  695.